package cn.com.zero.manager.auth.service.impl;

import cn.com.zero.api.auth.util.UserCacheKeyUtil;
import cn.com.zero.base.exception.ErrorCodeException;
import cn.com.zero.base.service.BaseService;
import cn.com.zero.base.util.RedisUtil;
import cn.com.zero.base.util.SensitiveInfoUtil;
import cn.com.zero.manager.auth.constant.ManagerAuthConstants;
import cn.com.zero.manager.auth.enums.LoginClientEnum;
import cn.com.zero.manager.auth.mapper.IManageMapper;
import cn.com.zero.manager.auth.po.ManagerPO;
import cn.com.zero.manager.auth.service.IManageService;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * @author guoxin
 * @version 1.0.0
 * @Description
 * @date 2023/4/7 9:38
 */
@Service
public class ManageService extends BaseService implements IManageService {

    /**
     * 管理员管理mapper
     */
    private IManageMapper manageMapper;

    /**
     * Redis工具类
     */
    private RedisUtil redisUtil;

    /**
     * 查询管理员列表
     *
     * @param userID    用户名
     * @param userName  用户名称
     * @param status    状态（0正常1冻结（禁用）2注销）
     * @return
     */
    @Override
    public List<ManagerPO> queryAdminList(String userID, String userName, Integer status) {
        return manageMapper.selectAdminList(userID,userName,status);
    }

    /**
     * 查询管理员详情
     *
     * @param userID    用户名
     * @return
     */
    @Override
    public ManagerPO queryAdmin(String userID) {
        return manageMapper.selectAdmin(userID);
    }

    /**
     * 添加管理员
     *
     * @param userId    登录名
     * @param userName  名称
     * @param password  密码
     * @param mobile    手机号
     * @param type      管理员类型 0 超级管理员  1 普通管理
     * @param note      备注信息
     * @param roles     角色编号
     */
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void addAdmin(String userId, String userName, String password, String mobile, Integer type, String note, String[] roles) {
        ManagerPO managerPO = manageMapper.selectAdmin(userId);
        if(!Objects.isNull(managerPO)){
            logger.error("用户名{}已存在", userId);
            throw new ErrorCodeException(-1145180L);
        }
        if(!isExistUsername(userName)){
            logger.error("用户名称{}已存在", userName);
            throw new ErrorCodeException(-1145140L);
        }
        if(!isExistMobilePhone(mobile)){
            logger.error("电话号码{}已存在", mobile);
            throw new ErrorCodeException(-114517L);
        }
        String encode = SensitiveInfoUtil.encryptPwd(password);
        String encrypt = SensitiveInfoUtil.encryptMobile(mobile);
        String showMobile = SensitiveInfoUtil.encodeMobile(mobile);
        manageMapper.insertAdmin(userId,userName,encode,encrypt,showMobile,type,note);
        manageMapper.insertAdminRole(userId,roles);
    }

    /**
     * 修改管理员信息
     *
     * @param userId    登录名
     * @param userName  名称
     * @param mobile    手机号
     * @param status    状态（0正常1冻结（禁用）2注销）
     * @param note      备注信息
     * @param roles     角色编号
     */
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void updateAdminInfo(String userId, String userName, String mobile, Integer status, String note, String[] roles) {
        ManagerPO managerPO = manageMapper.selectAdmin(userId);
        if(Objects.isNull(managerPO)){
            logger.error("用户名{}不存在", userId);
            throw new ErrorCodeException(-114518L);
        }
        if (!ObjectUtil.isNull(manageMapper.selectOtherIsExistAdminByName(userName,userId))){
            logger.error("用户名称{}已存在", userName);
            throw new ErrorCodeException(-1145140L);
        }
        String encryptMobile = SensitiveInfoUtil.encryptMobile(mobile);
        if(!ObjectUtil.isNull(manageMapper.selectOtherIsExistAdminByMobile(encryptMobile,userId))){
            logger.error("电话号码{}已存在", mobile);
            throw new ErrorCodeException(-114517L);
        }
        String showMobile = SensitiveInfoUtil.encodeMobile(mobile);
        manageMapper.modifyAdminInfo(userId,userName,encryptMobile,showMobile,status,note);
        if(!Objects.equals(ManagerAuthConstants.NORMAL, status)){
            deleteOnlineManagerFormRedis(userId);
        }
        if(ArrayUtil.isNotEmpty(roles)){
            manageMapper.deleteAdminRole(userId);
            manageMapper.insertAdminRole(userId,roles);
            deleteOnlineManagerFormRedis(userId);
        }
    }

    /**
     * 从redis中删除线上用户信息
     *
     * @param userId        管理员id
     */
    private void deleteOnlineManagerFormRedis(String userId){
        Set<String> keySet = null;
        for (int i = LoginClientEnum.PC_WEB.getValue();i <= LoginClientEnum.MOBILE.getValue();i++){
            keySet.add(UserCacheKeyUtil.getOnlineUserCacheKey(ManagerAuthConstants.MANAGER_SIDE_NAME, String.valueOf(i), userId));
            keySet.add(UserCacheKeyUtil.getMenuPermissionCacheKey(ManagerAuthConstants.MANAGER_SIDE_NAME, String.valueOf(i), userId));
            keySet.add(UserCacheKeyUtil.getUserTokenIssueTimeCacheKey(ManagerAuthConstants.MANAGER_SIDE_NAME, String.valueOf(i), userId));
        }
        redisUtil.delete(keySet);
    }

    /**
     * 重置管理员密码
     *
     * @param userId    登录名
     * @param password  密码
     */
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void resetPassword(String userId, String password) {
        ManagerPO managerPO = manageMapper.selectAdmin(userId);
        if(Objects.isNull(managerPO)){
            logger.error("用户名{}不存在", userId);
            throw new ErrorCodeException(-114518L);
        }
        manageMapper.resettingPassword(userId,SensitiveInfoUtil.encryptPwd(password));
    }

    /**
     * 修改管理员状态
     *
     * @param userId    登录名
     * @param status    状态（0正常1冻结（禁用）2注销）
     */
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void updateStatus(String userId, Integer status) {
        ManagerPO managerPO = manageMapper.selectAdmin(userId);
        if(Objects.isNull(managerPO)){
            logger.error("用户名{}不存在", userId);
            throw new ErrorCodeException(-114518L);
        }
        if(!Objects.equals(status, ManagerAuthConstants.NORMAL)){
            deleteOnlineManagerFormRedis(userId);
        }
    }

    /**
     * 删除管理员
     *
     * @param admins    管理员编号
     */
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void deleteAdminBatch(String[] admins) {
        manageMapper.deleteAdmin(admins);
        manageMapper.deleteAdminRoles(admins);
        for (String admin : admins) {
            deleteOnlineManagerFormRedis(admin);
        }
    }

    /**
     * 查询管理员拥有的角色
     *
     * @param userId    登录名
     * @return
     */
    @Override
    public String[] queryAdminRoleList(String userId) {
        return manageMapper.selectAdminRoleList(userId);
    }

    /**
     * 重置管理员角色
     *
     * @param userId    登录名
     * @param roles     角色编号数组
     */
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public void resetRole(String userId, String[] roles) {
        ManagerPO managerPO = manageMapper.selectAdmin(userId);
        if(Objects.isNull(managerPO)){
            logger.error("用户名{}不存在", userId);
            throw new ErrorCodeException(-114518L);
        }
        manageMapper.deleteAdminRole(userId);
        manageMapper.insertAdminRole(userId,roles);
    }

    /**
     * 检查登录名是否存在
     *
     * @param username  用户名称
     * @return
     */
    @Override
    public boolean isExistUsername(String username) {
        ManagerPO managerPO = manageMapper.selectIsExistAdminByName(username);
        return !Objects.isNull(managerPO);
    }

    /**
     * 检查手机号是否存在
     *
     * @param mobile  手机号
     * @return
     */
    @Override
    public boolean isExistMobilePhone(String mobile) {
        String encrypt = SensitiveInfoUtil.encryptMobile(mobile);
        ManagerPO managerByMobilePO = manageMapper.selectIsExistAdminByMobile(encrypt);
        return !Objects.isNull(managerByMobilePO);
    }

    @Autowired
    public void setManageMapper(IManageMapper manageMapper) {
        this.manageMapper = manageMapper;
    }

    @Autowired
    public void setRedisUtil(RedisUtil redisUtil) {
        this.redisUtil = redisUtil;
    }
}
